package com.ming_za.odupdaterserver.core.controller.web;

import com.ming_za.odupdaterserver.api.Updater;
import com.ming_za.odupdaterserver.core.exception.ROEnum;
import com.ming_za.odupdaterserver.core.service.ReturnBusinessPackage;
import com.ming_za.odupdaterserver.core.service.res.obj.MainUpdateItem;
import com.ming_za.odupdaterserver.core.sqlite.domain.Label;
import com.ming_za.odupdaterserver.core.utils.Msg;
import com.ming_za.odupdaterserver.core.utils.VersionUtils;
import com.ming_za.odupdaterserver.core.vo.R;
import com.ming_za.odupdaterserver.core.vo.VoUtils;
import com.ming_za.odupdaterserver.core.vo.req.*;
import com.ming_za.odupdaterserver.core.vo.resp.LabelResp;
import com.ming_za.odupdaterserver.core.vo.resp.ResAssociatedVersionResp;
import com.ming_za.odupdaterserver.core.vo.resp.VersionInfoResp;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Tag(name = "管理更新相关API")
@RestController
@RequestMapping("/sev-v")
public class AdminUpdaterAPI {

    private final Updater updater;
    private final VoUtils voUtils;

    public AdminUpdaterAPI(Updater updater, VoUtils voUtils) {
        this.updater = updater;
        this.voUtils = voUtils;
    }

    //TODO 新增写入类型功能
    @Operation(summary = "新增资源-返回资源id")
    @PutMapping("/res")
    public R<Long> addRes(HttpServletRequest request, @Valid ResAddVo res, @RequestParam(value = "file",required = false) MultipartFile file) throws IOException {
        ReturnBusinessPackage<Long> rbp = updater.addRes(res, file == null ? null : file.getInputStream());
        if (rbp.isSuccess()){
            Msg.getInstance().info("&f[" + request.getRemoteHost() + "]新增资源：" + res.getClientPath());
        }
        return R.pack(rbp.getCode(),rbp.getData());
    }

    @Operation(summary = "新增未发布版本")
    @PutMapping("/newVersion")
    public R<?> addUnPublicVersion(HttpServletRequest request) {
        ReturnBusinessPackage<Void> rbp = updater.newVersion();
        if (rbp.isSuccess()){
            Msg.getInstance().info("&a[" + request.getRemoteHost() + "]创建了一个新版本");
        }
        return R.pack(rbp.getCode(),rbp.getData());
    }

    @Operation(summary = "新增标签-返回标签id")
    @PostMapping("/label")
    public R<Long> addLabel(HttpServletRequest request,@RequestBody @Valid LabelAddVo labelAddVo){
        Msg.getInstance().info("&a[" + request.getRemoteHost() + "]新建标签:" + labelAddVo.getName());
        return R.ok(updater.addLabel(labelAddVo.getName(),labelAddVo.getParent()));
    }

    @Operation(summary = "修改标签父级")
    @PostMapping("/labelParent")
    public R<?> setLabelParent(@RequestBody @Valid LabelModifyParentVo labelModifyParentVo){
        ReturnBusinessPackage<Void> voidReturnBusinessPackage = updater.setLabelParent(labelModifyParentVo.getId(), labelModifyParentVo.getParent());
        return R.pack(voidReturnBusinessPackage.getCode());
    }

    @Operation(summary = "获取传入资源对版本的影响")
    @GetMapping("/influence/ResOnVersion")
    public R<List<ResAssociatedVersionResp>> getInfluenceOfResOnVersion(@RequestBody @Schema(description = "资源id数组") Long[] resId){
        return R.ok(updater.getInfluenceOfResOnVersion(resId));
    }

    @Operation(summary = "获取传入资源对版本的影响-返回受影响的资源id")
    @GetMapping("/influence/LabelOnRes")
    public R<List<Long>> getInfluenceOfLabelOnRes(@RequestBody @Schema(description = "标签id") long labelId){
        ReturnBusinessPackage<List<Long>> rbp = updater.getInfluenceOfLabelOnRes(labelId);
        return R.pack(rbp.getCode(),rbp.getData());
    }

    @Operation(summary = "获取传入标签受影响的所有子级")
    @GetMapping("/influence/LabelOnExtends/{labelId}")
    public R<List<LabelResp>> getInfluenceOfLabelOnExtends(@PathVariable("labelId") @Schema(description = "标签id") long labelId){
        ReturnBusinessPackage<List<Label>> rbp = updater.getInfluenceOfLabelOnExtends(labelId);

        if (!rbp.isSuccess()){
            return R.pack(rbp.getCode());
        }

        List<Label> influenceOfLabelOnExtends = rbp.getData();
        if (influenceOfLabelOnExtends != null){
            return R.ok(influenceOfLabelOnExtends.stream()
                    .map(label -> voUtils.cover(label,new LabelResp())).toList());
        }else {
            ROEnum updateNotfoundLabel = ROEnum.UPDATE_NOTFOUND_LABEL;
            return R.error(updateNotfoundLabel.getCode(),updateNotfoundLabel.getDefaultMsg());
        }

    }

    @Operation(summary = "获取所有标签")
    @GetMapping("/label/all")
    public R<List<LabelResp>> getAllLabel(){
        return R.ok(updater.getAllLabel().stream()
                .map(label -> voUtils.cover(label,new LabelResp())).toList());
    }

    @Operation(summary = "删除资源")
    @PostMapping("/delRes")
    public R<?> delRes(HttpServletRequest request,@RequestBody @Valid DelResVo delResVo){
        ReturnBusinessPackage<Void> rbp = updater.delRes(delResVo.getResId(), delResVo.getVersion());
        if (rbp.isSuccess()){
            Msg.getInstance().info("&f[" + request.getRemoteHost() + "]删除资源：" + Arrays.toString(delResVo.getResId()));
        }
        return R.pack(rbp.getCode());
    }

    @Operation(summary = "设置资源标签")
    @PostMapping("/modify/label")
    public R<?> setResLabel(@RequestBody @Valid SetResLabelVo[] setResLabelVo){
        updater.setResLabel(setResLabelVo);
        return R.ok();
    }

    @Operation(summary = "设置资源客户端路径")
    @PostMapping("/modify/path")
    public R<?> setClientPath(@RequestBody @Valid SetResClientPathVo[] setResClientPathVo){
        updater.setClientPath(setResClientPathVo);
        return R.ok();
    }

    @Parameters({
            @Parameter(name = "labelId",description = "标签id",in = ParameterIn.PATH,required = true)
    })
    @Operation(summary = "删除资源标签")
    @DeleteMapping("/modify/label/{labelId}")
    public R<?> delResLabel(HttpServletRequest request,@PathVariable("labelId") long labelId){
        ReturnBusinessPackage<Void> rbp = updater.delLabel(labelId);
        if (rbp.isSuccess()){
            Msg.getInstance().info("&f[" + request.getRemoteHost() + "]删除标签，id:" + labelId);
        }
        return R.pack(rbp.getCode());
    }

    @Parameters({
            @Parameter(name = "version",description = "新版本号",in = ParameterIn.PATH,required = true)
    })
    @Operation(summary = "修改未发布版的版本号")
    @PostMapping("/version/{version}")
    public R<?> modifyVersion(@PathVariable("version") int version){
        ReturnBusinessPackage<Void> rbp = updater.modifyVersion(version);
        return R.ok(rbp.getCode());
    }

    @Parameters({
            @Parameter(name = "version",description = "版本号",in = ParameterIn.PATH,required = true)
    })
    @Operation(summary = "删除版本")
    @DeleteMapping("/version/{version}")
    public R<?> delVersion(HttpServletRequest request,@PathVariable("version") int version){
        ReturnBusinessPackage<Void> rbp = updater.removeVersion(version);
        if(rbp.isSuccess()){
            Msg.getInstance().info("&f[" + request.getRemoteHost() + "]删除版本：" + VersionUtils.transformVersion(version));
        }
        return R.pack(rbp.getCode());
    }

    @Operation(summary = "获取所有版本详细信息")
    @GetMapping("/allVersion")
    public R<List<VersionInfoResp>> getAllVersionInfo(){
        return R.ok(updater.getAllVersionInfo());
    }

    @Operation(summary = "发布版本",description = "仅可存在一个未发布版，所以无需传入版本号")
    @PostMapping("/publishedVersion")
    public R<?> publishedVersion(HttpServletRequest request){
        ReturnBusinessPackage<Object> rbp = updater.publishedVersion();
        if (rbp.isSuccess()){
            Msg.getInstance().info("&a[" + request.getRemoteHost() + "]发布版本：" + VersionUtils.transformVersion((Integer) rbp.getData()));
            return R.pack(rbp.getCode());
        }else {
            return R.pack(rbp.getCode(),rbp.getData());
        }
    }

    @Parameters({
            @Parameter(name = "version",description = "版本号",in = ParameterIn.PATH,required = true)
    })
    @Operation(summary = "获取版本的所有资源")
    @GetMapping("/versionRes/{version}")
    public R<List<MainUpdateItem>> getVersionResAll(@PathVariable("version") Integer version){
        ReturnBusinessPackage<List<MainUpdateItem>> versionResAll = updater.getVersionResAll(version);

        return R.pack(versionResAll.getCode(),versionResAll.getData());
    }
}
